/*
 * CS_BLACKSMITH_MAGIC_REFINE.cpp
 *
 *  Created on: 2014. 3. 24.
 *      Author: mega
 */

#include "../../Command.h"
#include "../../User.h"
#include "../../NUtil/Utils.h"
#include "../../NLogic/Bag.h"
#include "../../NLogic/Item.h"
#include "../../NLogic/Function.h"
#include "../../NLogic/VirtualCurrency.h"
#include "../../NResource/Static.h"

namespace ProjectZ { namespace NCommand {

static void SendFailMagicRefine(User * pUser, int ack)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack);
	pAck->MakePacket(CMD_SC_BLACKSMITH_MAGIC_REFINE);
	pUser->Send(pAck);
}

void Command::CS_BLACKSMITH_MAGIC_REFINE(User * pUser, ::Network::Packet * pPacket)
{
/*	// 마법 제런
	ZNO_CS_BLACKSMITH_MAGIC_REFINE 			0x220C
	{
		u8	u8refine_stone_count;		// 마법석 갯수
		u64	u64item_seq;				// 아이템 seq
		u8	u8bag_type;
	}

	// 제련 응답
	ZNO_SC_BLACKSMITH_MAGIC_REFINE 			0x220D
	{
		s16	s16_ack;			// 제련 결과 (성공, 실패) : 실패 ack 따로 만들건지?
		u64	u64item_seq;		// 아이템 seq
		u8	u8bag_type;
	}*/

	PREPARE_PACKET;

	uint8_t magic_stone_count = 0;
	uint64_t item_seq = 0;
	uint8_t bag_type = 0;

	*pPacket >> magic_stone_count >> item_seq >> bag_type;

	if (0 >= magic_stone_count || 5 < magic_stone_count)
	{
		DEBUGLOG("%s : Invalid Stone Count=%d", __FUNCTION__, magic_stone_count);
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Bag * pBag = pUser->GetBag(static_cast<INVEN_BAG_TYPE>(bag_type));
	if (NULL == pBag)
	{
		DEBUGLOG("%s : pBag is NULL", __FUNCTION__);
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NLogic::Item * pItem = pBag->GetItem(item_seq);
	if (NULL == pItem)
	{
		DEBUGLOG("%s : pItem is NULL", __FUNCTION__);
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	if (false == NResource::Static::Instance().GetItemResource()->isEquip(pItem->GetData()))
	{
		DEBUGLOG("%s : INVALID SHEET TYPE=%d", __FUNCTION__, pItem->GetData().sub_type);
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 일반 제련 단계가 MAX가 아닌 경우
	if (pItem->GetData().max_enhance_step > pItem->GetData().cur_refine_step)
	{
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 마법 제련 단계가 이미 MAX인 경우
	if (5 <= pItem->GetData().ability_enhance_rate)
	{
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 제련 가격 확인Item Default Upgrade Rate Get Fail!!
	int vc_index = 0;
	switch (pItem->GetData().ability_enhance_rate)
	{
	case 0 : vc_index = static_cast<int>(EnumVCIndex::EM_VCINDEX_MAGIC_REFINE_1); break;
	case 1 : vc_index = static_cast<int>(EnumVCIndex::EM_VCINDEX_MAGIC_REFINE_2); break;
	case 2 : vc_index = static_cast<int>(EnumVCIndex::EM_VCINDEX_MAGIC_REFINE_3); break;
	case 3 : vc_index = static_cast<int>(EnumVCIndex::EM_VCINDEX_MAGIC_REFINE_4); break;
	case 4 : vc_index = static_cast<int>(EnumVCIndex::EM_VCINDEX_MAGIC_REFINE_5); break;
	}

	NResource::VCResource::Flyweight * pFly = NResource::Static::Instance().GetVCRef()->GetFly(vc_index);
	if (NULL == pFly)
	{
		DEBUGLOG("%s : pFly is NULL", __FUNCTION__);
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	int magic_refine_price = pFly->_VC_PRICE * magic_stone_count * -1;
	if (pUser->GetVirtualCurrency()->GetZen() < magic_refine_price)
	{
		SendFailMagicRefine(pUser, ACK_NOT_ENOUGH_ZEN);
		return;
	}

	// 마법 제련 확률 계산
	int default_rate = 0;
	if (false == NResource::Static::Instance().GetMagicRefineResource()->GetDefaultRate(pItem, default_rate))
	{
		DEBUGLOG("%s : Default Rate Get Fail!!", __FUNCTION__);
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	int magic_stone_rate = 0;
	if (false == NResource::Static::Instance().GetMagicRefineResource()->GetRatePerMagicStone(magic_stone_rate))
	{
		DEBUGLOG("%s : Magic Stone Rate Get Fail!!", __FUNCTION__);
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	int refine_rate = default_rate + (magic_stone_rate * magic_stone_count);
	int rand_rate = rand() % 1000;

	// 마법 제련 실패
	if (rand_rate > refine_rate)
	{
		if (5 <= magic_stone_count)
		{
			SendFailMagicRefine(pUser, ACK_ITEM_REFINE_FAIL_PROTECT);
		}
		else
		{
			// 아이템 파괴 확률 계산
			int destroy_rate = 0;
			if (false == NResource::Static::Instance().GetMagicRefineResource()->GetItemDestroyRate(pUser, destroy_rate))
			{
				DEBUGLOG("%s : Item Destroy Rate Get Fail!!", __FUNCTION__);
				SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
				return;
			}

			int destroy_rand_rate = rand() % 100;

			if (destroy_rand_rate < destroy_rate)
			{
				pBag->PopItem(item_seq);
				pItem->DeleteDatabaseItemInfo(NLogic::Item::ItemStatus::EM_ITEM_STATUS_MAGIC_REFINE_DESTROY);
				SendFailMagicRefine(pUser, ACK_ITEM_REFINE_FAIL_DESTROY);
			}
			else
			{
				SendFailMagicRefine(pUser, ACK_ITEM_REFINE_FAIL_PROTECT);
			}
		}

		NLogic::NFunction::VCProcess(pUser, vc_index, magic_refine_price);

		return;
	}

	// 마법 제련 성공 (능력치 상승)
	int upgrade_rate = 0;
	if (false == NResource::Static::Instance().GetMagicRefineResource()->GetItemDefaultUpgradeRate(upgrade_rate))
	{
		DEBUGLOG("%s : Item Default Upgrade Rate Get Fail!!", __FUNCTION__);
		SendFailMagicRefine(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	int new_effect_value = NUtil::AddPercentage(pItem->GetData().eff_value[0], upgrade_rate);
	if (new_effect_value == pItem->GetData().eff_value[0])
	{
		pItem->GetData().eff_value[0] += 1;
	}
	else
	{
		pItem->GetData().eff_value[0] = new_effect_value;
	}

	// 마법 제련 단계 상승
	pItem->GetData().ability_enhance_rate += 1;

	if (false == pItem->UpdateDatabaseItemInfo())
	{
		DEBUGLOG("%s : Item Update Fail", __FUNCTION__);
		SendFailMagicRefine(pUser, ACK_DB_ERROR);
		return;
	}

	// 응답
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ACK_OK) << item_seq << bag_type;
	pAck->MakePacket(CMD_SC_BLACKSMITH_MAGIC_REFINE);
	pUser->Send(pAck);

	// VC 처리
	NLogic::NFunction::VCProcess(pUser, vc_index, magic_refine_price);
}

} /*NCommand*/ } /*ProjectZ*/


